package com.newtype.meeting.client.mvc.frontend;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.newtype.meeting.client.AppEvents;
import com.newtype.meeting.client.FrequencySourceData;
import com.newtype.meeting.client.GMeeting;
import com.newtype.meeting.client.model.Account;
import com.newtype.meeting.client.model.Meeting;
import com.newtype.meeting.client.model.MeetingNotify;
import com.newtype.meeting.client.model.MeetingRecord;
import com.newtype.meeting.client.model.MeetingReport;
import com.newtype.meeting.client.model.MeetingStart;
import com.newtype.meeting.client.service.MeetingServiceAsync;
import com.newtype.meeting.client.service.MeetingStartServiceAsync;
import com.newtype.meeting.shared.MeetingNotifyDTO;

public class MeetingController extends Controller {
	private MeetingStartServiceAsync startService;
	private MeetingServiceAsync meetingService;
	private MeetingView meetingView;

	private Account account;

	public MeetingController() {
		registerEventTypes(AppEvents.ViewMeeting);
		registerEventTypes(AppEvents.SaveMeeting);
		registerEventTypes(AppEvents.ToMeetingContent);
		registerEventTypes(AppEvents.ToEditMeetingContent);
		registerEventTypes(AppEvents.CancelMeeting);
		registerEventTypes(AppEvents.DeleteMeetingRecord);
		registerEventTypes(AppEvents.ToEditOpenTypeWindow);
		registerEventTypes(AppEvents.ToNamedTableWindow);
		registerEventTypes(AppEvents.ToMeetingNotice);
		registerEventTypes(AppEvents.ReplyMeetingNotify);
		registerEventTypes(AppEvents.UpdateOpenType);
	}

	@Override
	protected void initialize() {
		super.initialize();
		meetingView = new MeetingView(this);
		startService = Registry.get(GMeeting.MEETINGSTART_SERVICE);
		meetingService = Registry.get(GMeeting.MEETING_SERVICE);

		account = Registry.get(GMeeting.ACCOUNT);
	}

	@Override
	public void handleEvent(AppEvent event) {
		EventType type = event.getType();
		if (type == AppEvents.ViewMeeting) {
			onViewMeeting(event);
		} else if (type == AppEvents.SaveMeeting) {
			onSaveMeeting(event);
		} else if (type == AppEvents.ToMeetingContent) {
			onToMeetingContent(event);
		} else if (type == AppEvents.ToEditMeetingContent) {
			onEditMeetingContent(event);
		} else if (type == AppEvents.CancelMeeting) {
			onCancelMeeting(event);
		} else if (type == AppEvents.DeleteMeetingRecord) {
			onDeleteMeetingRecord(event);
		} else if (type == AppEvents.ToEditOpenTypeWindow) {
			onToEditOpenTypeWindow(event);
		} else if (type == AppEvents.ToNamedTableWindow) {
			onToNamedTableWindow(event);
		} else if (type == AppEvents.ToMeetingNotice) {
			onToToMeetingNotice(event);
		} else if (type == AppEvents.ReplyMeetingNotify) {
			onReplyMeetingNotify(event);
		} else if (type == AppEvents.UpdateOpenType) {
			onUpdateOpenType(event);
		}
	}

	/**
	 * 修改会议公开对象
	 * @param event
	 */
	private void onUpdateOpenType(AppEvent event) {
		final Meeting meeting = event.getData();
		meetingService.saveMeeting(meeting, new AsyncCallback<Meeting>() {
			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);
			}

			@Override
			public void onSuccess(Meeting result) {
				MessageBox.alert("提示信息", "公开对象修改成功", null);
				Dispatcher.forwardEvent(AppEvents.ToMeetingContent, meeting
						.getId());
			}
		});
	}

	/**
	 * 回复会议通知
	 * @param event
	 */
	private void onReplyMeetingNotify(AppEvent event) {
		MeetingNotify notify = event.getData();
		meetingService.saveMeetingNotify(notify, new AsyncCallback<Void>() {

			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);

			}

			@Override
			public void onSuccess(Void result) {
				MessageBox.alert("提示信息", "会议通知回复成功", null);
				Dispatcher.forwardEvent(AppEvents.ViewMeeting);
			}

		});
	}

	/**
	 * 跳转至回复会议通知面板
	 * @param event
	 */
	private void onToToMeetingNotice(AppEvent event) {
		final AppEvent ae = new AppEvent(event.getType());
		//接收参数
		final MeetingNotifyDTO notifyDTO = event.getData();
		meetingService.getMeeting(notifyDTO.getMeetingID(),
				new AsyncCallback<Meeting>() {
					@Override
					public void onFailure(Throwable caught) {
						Dispatcher.forwardEvent(AppEvents.Error, caught);
					}

					@Override
					public void onSuccess(Meeting result) {
						ae.setData("meeting", result);
						//获取MeetingNotify对象
						meetingService.getMeetingNotify(notifyDTO.getId(),
								new AsyncCallback<MeetingNotify>() {
									@Override
									public void onFailure(Throwable caught) {
										Dispatcher.forwardEvent(
												AppEvents.Error, caught);
									}

									@Override
									public void onSuccess(MeetingNotify result) {
										final MeetingNotify notify = result;
										if (notify.getReadDate() == null) {
											notify.setReadDate(new Date());
											//更新阅读时间
											meetingService.saveMeetingNotify(
													notify,
													new AsyncCallback<Void>() {
														@Override
														public void onFailure(
																Throwable caught) {
															Dispatcher
																	.forwardEvent(
																			AppEvents.Error,
																			caught);
														}

														@Override
														public void onSuccess(
																Void result) {
															ae.setData(
																	"notify",
																	notify);
															forwardToView(
																	meetingView,
																	ae);
														}
													});
										} else {
											ae.setData("notify", notify);
											forwardToView(meetingView, ae);
										}
									}
								});
					}
				});

	}

	/**
	 * 弹出点名窗口
	 * @param event
	 */
	private void onToNamedTableWindow(AppEvent event) {
		//接收参数
		Meeting meeting = event.getData();
		final AppEvent ae = new AppEvent(event.getType());
		meetingService.listMeetingNotify(meeting.getId(),
				new AsyncCallback<List<MeetingNotifyDTO>>() {
					@Override
					public void onFailure(Throwable caught) {
						Dispatcher.forwardEvent(AppEvents.Error, caught);
					}

					@Override
					public void onSuccess(List<MeetingNotifyDTO> result) {
						List<MeetingNotifyDTO> subscribe = new ArrayList<MeetingNotifyDTO>();
						List<MeetingNotifyDTO> incapable = new ArrayList<MeetingNotifyDTO>();
						List<MeetingNotifyDTO> notyet = new ArrayList<MeetingNotifyDTO>();
						for (MeetingNotifyDTO m : result) {
							if (m.getAttendTAG() != null
									&& m.getAttendTAG() == 1) {
								subscribe.add(m);
							} else if (m.getAttendTAG() != null
									&& m.getAttendTAG() == 0) {
								incapable.add(m);
							} else {
								notyet.add(m);
							}
						}
						ae.setData("subscribe", subscribe);
						ae.setData("incapable", incapable);
						ae.setData("notyet", notyet);
						forwardToView(meetingView, ae);
					}
				});
	}

	/**
	 * 弹出修改会议公开对象窗口
	 * @param event
	 */
	private void onToEditOpenTypeWindow(AppEvent event) {
		forwardToView(meetingView, event);
	}

	/**
	 * 删除会议记录
	 * @param event
	 */
	private void onDeleteMeetingRecord(AppEvent event) {
		final MeetingRecord record = event.getData();
		meetingService.deleteMeetingRecord(record.getId(),
				new AsyncCallback<Void>() {
					@Override
					public void onFailure(Throwable caught) {
						Dispatcher.forwardEvent(AppEvents.Error, caught);
					}

					@Override
					public void onSuccess(Void result) {
						MessageBox.alert("提示信息", "会议记录删除成功", null);
						Dispatcher.forwardEvent(AppEvents.ToMeetingContent,
								record.getMeetingID());
					}
				});
	}

	/**
	 * 取消本次会议
	 * @param event
	 */
	private void onCancelMeeting(AppEvent event) {
		Meeting meeting = event.getData();
		meetingService.cancelMeeting(meeting.getId(),
				new AsyncCallback<Void>() {
					@Override
					public void onFailure(Throwable caught) {
						Dispatcher.forwardEvent(AppEvents.Error, caught);
					}

					@Override
					public void onSuccess(Void result) {
						MessageBox.alert("提示信息", "会议取消成功", null);
						Dispatcher.forwardEvent(AppEvents.ViewMeeting);
					}
				});
	}

	/**
	 * 执行跳转到修改会议内容框口
	 * @param event
	 */
	private void onEditMeetingContent(AppEvent event) {
		forwardToView(meetingView, event);
	}

	/** 跳转到会议内容面板 */
	private void onToMeetingContent(AppEvent event) {
		final AppEvent ae = new AppEvent(event.getType());
		//接收参数
		final String id = event.getData();
		meetingService.getMeeting(id, new AsyncCallback<Meeting>() {
			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);
			}

			@Override
			public void onSuccess(Meeting result) {
				ae.setData("meeting", result);
				//会议记录
				meetingService.listMeetingRecord(id,
						new AsyncCallback<List<MeetingRecord>>() {
							@Override
							public void onFailure(Throwable caught) {
								Dispatcher
										.forwardEvent(AppEvents.Error, caught);
							}

							@Override
							public void onSuccess(List<MeetingRecord> result) {
								ae.setData("records", result);
								//会议报告
								meetingService
										.listMeetingReport(
												id,
												new AsyncCallback<List<MeetingReport>>() {
													@Override
													public void onFailure(
															Throwable caught) {
														Dispatcher
																.forwardEvent(
																		AppEvents.Error,
																		caught);
													}

													@Override
													public void onSuccess(
															List<MeetingReport> result) {
														ae.setData("reports",
																result);
														//会议通知者
														meetingService
																.listMeetingNotify(
																		id,
																		new AsyncCallback<List<MeetingNotifyDTO>>() {
																			@Override
																			public void onFailure(
																					Throwable caught) {
																				Dispatcher
																						.forwardEvent(
																								AppEvents.Error,
																								caught);
																			}

																			@Override
																			public void onSuccess(
																					List<MeetingNotifyDTO> result) {
																				List<MeetingNotifyDTO> notices = new ArrayList<MeetingNotifyDTO>();
																				for (MeetingNotifyDTO notify : result) {
																					if (notify
																							.getAttendTAG() != null
																							&& notify
																									.getAttendTAG() == 1) {
																						notices
																								.add(notify);
																					}
																				}
																				ae
																						.setData(
																								"notices",
																								notices);
																				forwardToView(
																						meetingView,
																						ae);
																			}
																		});
													}
												});
							}
						});
			}
		});
	}

	/**
	 * 送出保存会议信息
	 * @param event
	 */
	private void onSaveMeeting(AppEvent event) {
		DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd");
		//接收参数
		MeetingStart start = event.getData();
		Date startDate = start.getStartDate();//开始日期
		Date endDate = start.getEndDate();//结束日期
		//日期进行格式化
		String sDate = dtf.format(startDate);
		String eDate = dtf.format(endDate);
		startDate = dtf.parse(sDate);
		endDate = dtf.parse(eDate);

		int frequency = start.getNFrequency();//周期
		int dateSeq = start.getNDateSeq();//频率
		int dateValue = start.getNDateValue();//星期/日期值

		if (frequency == 0) {//单一日期
			List<Date> days = new ArrayList<Date>();
			if (startDate.compareTo(endDate) == 0) {
				days.add(startDate);
			}
			verifySaveMeeting(start, days);
		} else if (frequency == 1) {//每周
			List<Date> days = FrequencySourceData.getDayOfWeek(startDate,
					endDate, dateValue);
			verifySaveMeeting(start, days);
		} else if (frequency == 2) {//每月
			if (dateSeq == 100) {//固定日期
				List<Date> days = FrequencySourceData.getDayOfMonth(startDate,
						endDate, dateValue);
				verifySaveMeeting(start, days);
			} else {//周期
				List<Date> days = FrequencySourceData.getWeekDayOfMonth(
						startDate, endDate, dateSeq, dateValue);
				verifySaveMeeting(start, days);
			}
		}
	}

	/**
	 * 校验日期并保存会议记录
	 * @param start 开始会议对象
	 * @param days 日期集合
	 */
	private void verifySaveMeeting(MeetingStart start, List<Date> days) {
		if (days.size() > 0) {
			for (Date day : days) {
				saveNewMeeting(start, day);
			}
			MessageBox.alert("提示信息", "送出成功", null);
			Dispatcher.forwardEvent(AppEvents.ViewMeeting);
		} else {
			MessageBox.alert("提示信息", "没有找到指定日期，请重新选择！", null);
		}
	}

	/**
	 * 保存一个新的Meeting对象
	 * @param day
	 * @return
	 */
	private void saveNewMeeting(MeetingStart start, Date day) {
		//实例化一个新的Meeting对象
		Meeting meeting = new Meeting(start);
		meeting.setNotifierID(account.getAccountID());//通知者
		meeting.setSubmitDate(new Date());//提交时间
		meeting.setStartDate(day);
		meeting.setEndDate(day);
		meetingService.saveMeeting(meeting, new AsyncCallback<Meeting>() {
			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);
			}

			@Override
			public void onSuccess(Meeting result) {
				// 生成会议通知
				createMeetingNotify(result);
			}
		});
	}

	//生成会议通知
	protected void createMeetingNotify(Meeting meeting) {
		String[] sArray = meeting.getInvitedID().split(", ");
		for (String string : sArray) {
			MeetingNotify notify = new MeetingNotify();
			notify.setMeetingID(meeting.getId());
			notify.setAccountID(string);
			notify.setHtmlTAG(0);
			notify.setSubmitDate(new Date());
			notify.setDelTAG(0);
			notify.setTempTAG(0);
			meetingService.saveMeetingNotify(notify, new AsyncCallback<Void>() {
				@Override
				public void onFailure(Throwable caught) {
					Dispatcher.forwardEvent(AppEvents.Error, caught);
				}

				@Override
				public void onSuccess(Void result) {

				}
			});
		}
	}

	/**
	 * 查看会议内容页
	 * @param event
	 */
	private void onViewMeeting(final AppEvent event) {
		final AppEvent ae = new AppEvent(event.getType());
		//草稿
		startService.listMeetingStart(account.getAccountID(),
				new AsyncCallback<List<MeetingStart>>() {
					@Override
					public void onFailure(Throwable caught) {
						Dispatcher.forwardEvent(AppEvents.Error, caught);
					}

					@Override
					public void onSuccess(List<MeetingStart> result) {
						ae.setData("draft", result);
						//待召开与历史
						meetingService.listMeeting(account.getAccountID(),
								new AsyncCallback<List<Meeting>>() {
									@Override
									public void onFailure(Throwable caught) {
										Dispatcher.forwardEvent(
												AppEvents.Error, caught);
									}

									@Override
									public void onSuccess(List<Meeting> result) {
										List<Meeting> heldtoList = new ArrayList<Meeting>();
										List<Meeting> historyList = new ArrayList<Meeting>();
										for (Meeting meeting : result) {
											if (meeting.getStartDate().after(
													new Date())) {
												heldtoList.add(meeting);
											} else if (meeting.getStartDate()
													.before(new Date())) {
												historyList.add(meeting);
											}
										}
										ae.setData("heldto", heldtoList);
										ae.setData("history", historyList);

										//历史会议
										meetingService
												.listMeetingNotice(
														account.getAccountID(),
														new AsyncCallback<List<MeetingNotifyDTO>>() {
															@Override
															public void onFailure(
																	Throwable caught) {
																Dispatcher
																		.forwardEvent(
																				AppEvents.Error,
																				caught);
															}

															@Override
															public void onSuccess(
																	List<MeetingNotifyDTO> result) {
																List<MeetingNotifyDTO> dtos = new ArrayList<MeetingNotifyDTO>();
																for (MeetingNotifyDTO dto : result) {
																	if (dto
																			.getAttendTAG() == null) {
																		dtos
																				.add(dto);
																	}
																}
																ae
																		.setData(
																				"notice",
																				dtos);
																forwardToView(
																		meetingView,
																		ae);
															}
														});
									}
								});
					}
				});
	}
}
